Skip to content

fix: stop the badge sweep re-triggering SSO sign-in every cycle - #16

Open
marcioviniciusspiridigliozzi-dot wants to merge 1 commit into
nicojan:mainfrom
marcioviniciusspiridigliozzi-dot:fix/badge-sweep-sso-storm
Open

fix: stop the badge sweep re-triggering SSO sign-in every cycle#16
marcioviniciusspiridigliozzi-dot wants to merge 1 commit into
nicojan:mainfrom
marcioviniciusspiridigliozzi-dot:fix/badge-sweep-sso-storm

Conversation

@marcioviniciusspiridigliozzi-dot

Copy link
Copy Markdown
Contributor

The hibernated-badge sweep loads a service's real URL in a transient web view to read its badge. When that service's session has expired, the load is redirected to the identity provider and comes back with nothing. The next sweep does the same, and the one after that.

On an SSO tenant every one of those redirects is a fresh approval request. One user here saw 68 authenticator pushes in 14 hours from two services, arriving at the sweep's own cadence: 20 seconds apart within a cycle, 4m03s between cycles.

That is worth treating as more than an annoyance. Repeated unexplained push prompts are exactly the conditioning that MFA fatigue attacks rely on — someone who has learned to tap "approve" to make the buzzing stop is one prompt away from approving somebody else's sign-in.

Retrying can never help, either. A transient web view has no way to sign anyone in, so the sweep is generating approval requests it could not consume even if the user granted them.

The change

Park a service after two consecutive fetches that end off-host with no count, and let it back in the moment the user opens it — which is the only place a sign-in can actually be completed.

Two strikes rather than one because a slow hydrate can also finish off-host with nothing readable, and parking by mistake costs a stale badge until the service is next opened. That seemed the right way round: a late badge is cheap, a missed one is not.

The release runs first in the sweep. A service with a live web view is filtered out of the target list, so releasing later would leave it parked forever.

The decision itself is factored into AuthWallResolver.looksLikeSignInWall so it can be tested without a live web view — covered for the off-host-and-empty case, the same-host-and-empty case (an authenticated inbox that is simply empty), the redirected-but-counted case, and the unresolved-host case.

Note on CI

This branches from main, which currently has an intermittent StoreRepair test flake — I sent a separate fix for it in #15. Until that lands, a red run here is most likely that flake rather than this change. I re-ran this branch with #15's fix applied underneath: 0 failures in 8 runs, against 1 in 4 without it.

The sweep loads a hibernated service's real URL in a transient web view
to read its badge. When that service's session has expired, the load is
redirected to the identity provider and returns nothing — and the next
sweep does it again, and the one after that.

On an SSO tenant each of those redirects is a fresh approval request.
One user saw 68 authenticator pushes in 14 hours from two services,
arriving at the sweep's own cadence: 20s apart within a cycle, 4m03s
between cycles. Retrying can never help, because a transient web view
has no way to sign anyone in.

So park a service after two consecutive fetches that end off-host with
no count, and let it back in the moment the user opens it — which is
the only place a sign-in can actually be completed. The release runs
first in the sweep, because a service with a live web view is filtered
out of the target list and would otherwise stay parked forever.

Two strikes rather than one: a slow hydrate can also finish off-host
with nothing readable, and parking by mistake costs a stale badge until
the service is opened.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant